pub fn convert_base(num_str: &str, to_base: u32) -> String {
    // Parse and validate the num_str
    let parts: Vec<&str> = num_str.trim().split('(').collect();
    if parts.len() != 2 || !parts[1].ends_with(')') {
        return "Error: Invalid num_str format.".to_string();
    }

    let value = parts[0];
    let source_base: u32 = match parts[1][..parts[1].len() - 1].parse() {
        Ok(base) if (2..=16).contains(&base) => base,
        _ => return "Error: Invalid source base.".to_string(),
    };

    if !(2..=16).contains(&to_base) {
        return "Error: Supported bases are between 2 and 16.".to_string();
    }

    // Convert the value from the source base to decimal
    let decimal_value = match u32::from_str_radix(value, source_base) {
        Ok(num) => num,
        Err(_) => return "Error: Invalid number for the given source base.".to_string(),
    };

    // Convert the decimal value to the target base
    let mut num = decimal_value;
    let mut result = String::new();
    while num > 0 {
        let digit = num % to_base;
        result.push(std::char::from_digit(digit, to_base).unwrap());
        num /= to_base;
    }

    if result.is_empty() {
        result.push('0');
    }

    // Return only the number part (not the base annotation)
    result.chars().rev().collect::<String>()
}
